#ifndef TB_BASE_ARBITRARY_CAST_HPP__
#define TB_BASE_ARBITRARY_CAST_HPP__

#include <rapidjson/rapidjson.h>
#include <rapidjson/internal/dtoa.h>
#include <rapidjson/internal/strtod.h>

#include "string/string16.hpp"
#include "tostring.hpp"

TB_NAMESPACE_BEGIN

template <typename To, typename From> To ArbitraryCast(const From& v);

template <typename To, typename From, typename Enabled = void>
struct ArbitraryCastImpl {
	static To Cast(const From& v) {
		return _Cast<To, From>(v);
	}

	template <typename To, typename From>
	static To _Cast(const From& v) {
		(void)v;
		BOOST_STATIC_ASSERT(false);
		return To();
	}

	template <typename To, To>
	static To _Cast(const To& v) {
		return v;
	}

  template <>
  static _STD string _Cast(const bool& v) {
    return v ? "true" : "false";
  }

	template <>
	static _STD string _Cast(const uint8& v) {
		char buff[10];
		char* end = RAPIDJSON_NAMESPACE::internal::u32toa((uint32)v, buff);
		return _STD string(buff, end - buff);
	}

	template <>
	static _STD string _Cast(const int8& v) {
		char buff[10];
		char* end = RAPIDJSON_NAMESPACE::internal::i32toa((int32)v, buff);
		return _STD string(buff, end - buff);
	}

	template <>
	static _STD string _Cast(const uint16& v) {
		char buff[10];
		char* end = RAPIDJSON_NAMESPACE::internal::u32toa((uint32)v, buff);
		return _STD string(buff, end - buff);
	}

	template <>
	static _STD string _Cast(const int16& v) {
		char buff[10];
		char* end = RAPIDJSON_NAMESPACE::internal::i32toa((int32)v, buff);
		return _STD string(buff, end - buff);
	}

	template <>
	static _STD string _Cast(const uint32& v) {
		char buff[10];
		char* end = RAPIDJSON_NAMESPACE::internal::u32toa(v, buff);
		return _STD string(buff, end - buff);
	}

	template <>
	static _STD string _Cast(const int32& v) {
		char buff[10];
		char* end = RAPIDJSON_NAMESPACE::internal::i32toa(v, buff);
		return _STD string(buff, end - buff);
	}

	template <>
	static _STD string _Cast(const uint64& v) {
		char buff[20];
		char* end = RAPIDJSON_NAMESPACE::internal::u64toa(v, buff);
		return _STD string(buff, end - buff);
	}

	template <>
	static _STD string _Cast(const int64& v) {
		char buff[20];
		char* end = RAPIDJSON_NAMESPACE::internal::i64toa(v, buff);
		return _STD string(buff, end - buff);
	}

	template <>
	static _STD string _Cast(const float& v) {
		char buff[50]; //max 50 byte
		char* end = RAPIDJSON_NAMESPACE::internal::dtoa((double)v, buff);
		return _STD string(buff, end - buff);
	}

	template <>
	static _STD string _Cast(const double& v) {
		char buff[50]; //max 50 byte
		char* end = RAPIDJSON_NAMESPACE::internal::dtoa(v, buff);
		return _STD string(buff, end - buff);
	}
};

template <typename To, typename From>
struct ArbitraryCastImpl<To, From, typename enable_if<is_same<string16, To>::value >::type> {
	static To Cast(const From &v) {
		_STD string result = ArbitraryCast<_STD string>(v);
		return UTF8ToUTF16(result);
	}
};

template <typename To, typename From>
To ArbitraryCast(const From &v) {
	return ArbitraryCastImpl<To, From>::Cast(v);
}

TB_NAMESPACE_END

#endif // TB_BASE_ARBITRARY_CAST_HPP__
